package com.alinesno.cloud.initializr.starter.codegen.init.impl;

import java.io.File;
import java.io.IOException;
import java.util.Base64;
import java.util.Map;

import org.apache.commons.io.FileUtils;
import org.apache.tika.Tika;
import org.gitlab4j.api.GitLabApiException;
import org.gitlab4j.api.models.Project;
import org.gitlab4j.api.models.RepositoryFile;
import org.gitlab4j.api.models.User;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.client.RestClientException;
import org.springframework.web.client.RestTemplate;

import com.alibaba.fastjson.JSONObject;
import com.alinesno.cloud.initializr.starter.cicd.gitlab.common.Gitlab4jClient;
import com.alinesno.cloud.initializr.starter.cicd.gitlab.service.GroupService;
import com.alinesno.cloud.initializr.starter.cicd.gitlab.service.ProjectService;
import com.alinesno.cloud.initializr.starter.cicd.gitlab.service.RunnerService;
import com.alinesno.cloud.initializr.starter.codegen.init.InitProjectService;
import com.alinesno.cloud.initializr.starter.dto.GroupDto;
import com.alinesno.cloud.initializr.starter.entity.BuildGitEntity;
import com.alinesno.cloud.initializr.starter.seedgen.bean.ProjectInfoDto;

/**
 * 工程脚手架
 * 
 * @author WeiXiaoJin
 * @date 2021年6月21日 下午5:07:13
 */
@Service
public class InitProjectServiceImpl implements InitProjectService {

	private static final Logger log = LoggerFactory.getLogger(InitProjectServiceImpl.class);

	private Tika tika = new Tika();

//	@Autowired
//	private ProjectService gitlabProjectService;

	@Autowired
	private GroupService groupService;

	@Autowired
	private RunnerService runnerService;

	@Override
	public ProjectInfoDto initRepo(ProjectInfoDto info, Map<String, byte[]> data, Gitlab4jClient gitlab4jclient)
			throws GitLabApiException {
		// 1. 创建远程项目库
		ProjectService gitlabProjectService = new ProjectService();
		log.debug("gitlabProjectService = {}", gitlabProjectService);

		gitlabProjectService.setGitlab4jclient(gitlab4jclient);

		User user = gitlabProjectService.queryCurrentUser(gitlab4jclient);
		Integer userId = user.getId();

//		String groupName = info.getGroup().getName() ; //.getGitGroupName();
//		Group group = gitlabProjectService.queryGroupByName(groupName, userId);
//		Assert.notNull(group , "项目空间不存在或者没有权限.");

		GroupDto group = info.getGroup();
		String projectName = info.getProjectCode(); // .getProjectName();
		boolean visibility = false;

		Project project = gitlabProjectService.createProject(group, projectName, userId, visibility, gitlab4jclient);
		log.debug("project = {}", project);

		info.setGitProjectId(project.getId() + "");
		info.setGitProjectLink(project.getHttpUrlToRepo());
		info.setGitRunnersToken(project.getRunnersToken());

		// 2. 初始化项目库模板(gitflow)
		Integer projectId = project.getId();
		String commitMessage = "初始化工程";

		for (String gitPath : data.keySet()) {
			System.out.println("key = " + gitPath + " , value = " + data.get(gitPath));

			RepositoryFile repositoryFile = new RepositoryFile();
			repositoryFile.setFilePath(gitPath);
			repositoryFile.encodeAndSetContent(data.get(gitPath)); // .readFileToByteArray(sf)); // 二进制文件

			RepositoryFile createdFile = gitlabProjectService.getGitlab4jclient().getGitLabApi().getRepositoryFileApi()
					.createFile(projectId, repositoryFile, "master", commitMessage);
			log.debug("createdFile = " + createdFile);
		}

		// 3. 初始化工程模板库和分支，并填写分支RAEDME.md

		return info;

	}

	public void uploadDirectoryFile(File f, String path, Integer projectId, Integer userId,
			ProjectService gitlabProjectService) throws IOException {
		File[] fList = f.listFiles();
		for (File sf : fList) {
			if (sf.isDirectory()) {
				File ssF = sf;
				uploadDirectoryFile(ssF, path, projectId, userId, gitlabProjectService);
			} else {
				String gitPath = sf.getPath().substring(path.length() + 1, sf.getPath().length());
				String commitMessage = "xxxxx";

				String mimeType = tika.detect(sf);

				System.out.println("f = " + sf.getPath().substring(path.length() + 1, sf.getPath().length())
						+ " , mimeType = " + mimeType);

				try {
					RepositoryFile file = new RepositoryFile();
					file.setFilePath(gitPath);
					file.encodeAndSetContent(FileUtils.readFileToByteArray(sf)); // 二进制文件

					RepositoryFile createdFile = gitlabProjectService.getGitlab4jclient().getGitLabApi()
							.getRepositoryFileApi().createFile(projectId, file, "master", commitMessage);
					log.debug("createdFile = " + createdFile);

				} catch (GitLabApiException e) {
					e.printStackTrace();
				}
			}
		}
	}

	@Override
	public void initProject(ProjectInfoDto info) {

		// 1. Clone本地环境

		// 2. 生成初始版本代码

		// 3. 提交代码到基线
	}

	@Override
	public void initDocker(ProjectInfoDto info) {

		// 1. Gitlab构建镜像

		// 2. 镜像构建完成并发布

	}

	@Override
	public void uploadFileRepo(File file, String path, Integer projectId, Integer userId,
			ProjectService gitlabProjectService) {
		// 1. 初始化项目库模板(gitflow)
		try {
			uploadDirectoryFile(file, path, projectId, userId, gitlabProjectService);
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	@Override
	public void createGroup(String groupName) {
		// 1. 创建分组
		GroupDto group = new GroupDto();
		group.setName(groupName);
		group.setPath(groupName);
		groupService.createGroup(group, null);

		// 2. 分配账号权限
		groupService.createMember(null, null);
	}

	@Override
	public void createRunner(String runnerToken) {
		runnerService.createRunner(runnerToken);
	}

	@Override
	public ProjectInfoDto initGiteeRepo(ProjectInfoDto info, Map<String, byte[]> data, BuildGitEntity e) {

//		info.setProjectCode("testProj" + RandomUtil.getRandom().nextInt());
		
		String accessToken = e.getAccessPrivateToken();
		JSONObject json = JSONObject.parseObject(e.getBingGitInfo())  ; 
	
		String owner = json.getString("login")  ;
		
		createGiteeRepo(info, e , owner);

		String repo = info.getProjectCode() ; 
		String pushUrl = "https://gitee.com/api/v5/repos/" + owner + "/" + repo + "/contents/";
		
		log.debug("pushUrl = {}" , pushUrl);

		for (String gitPath : data.keySet()) {
			System.out.println("key = " + gitPath + " , value = " + data.get(gitPath) + ", path = " + data.get(gitPath).length);

			HttpHeaders requestHeaders = new HttpHeaders();
			requestHeaders.add("accept", "application/json");
			requestHeaders.add("Authorization", "token " + accessToken);

			RestTemplate restTemplate = new RestTemplate();

			// 封装参数，千万不要替换为Map与HashMap，否则参数无法传递
			MultiValueMap<String, Object> paramMap = new LinkedMultiValueMap<String, Object>();
			paramMap.add("access_token", accessToken);
			paramMap.add("owner", owner);
			paramMap.add("repo", info.getProjectCode());
			paramMap.add("path", gitPath);
			paramMap.add("branch", "master") ; 
			paramMap.add("content", Base64.getEncoder().encode(data.get(gitPath).length==0?("// init file").getBytes():data.get(gitPath))) ; 
			paramMap.add("message", "代码生成器初始化项目库");
			
			HttpEntity<MultiValueMap<String, Object>> requestEntity = new HttpEntity<MultiValueMap<String, Object>>(paramMap,requestHeaders);
			
			// get请求方式
			String pushFileUrl = pushUrl + gitPath;
			log.debug("pushFileUrl = {}" , pushFileUrl) ;
		
			if(!gitPath.endsWith("README.md")) {
				ResponseEntity<String> response = restTemplate.exchange(pushFileUrl, HttpMethod.POST, requestEntity, String.class);
				String pushInfo = response.getBody();
				log.debug("pushInfo = " + pushInfo);
			}
		}

		return info;
	}

	private void createGiteeRepo(ProjectInfoDto info, BuildGitEntity e, String owner) {
		String accessToken = e.getAccessPrivateToken();

		String createRepoUrl = "https://gitee.com/api/v5/user/repos";
		
		HttpHeaders requestHeaders = new HttpHeaders();
		requestHeaders.add("accept", "application/json");
		requestHeaders.add("Authorization", "token " + accessToken);

		RestTemplate restTemplate = new RestTemplate();
		
		// 封装参数，千万不要替换为Map与HashMap，否则参数无法传递
        MultiValueMap<String, Object> paramMap = new LinkedMultiValueMap<String, Object>();
        paramMap.add("name", info.getProjectCode());
        paramMap.add("auto_init", true);
        paramMap.add("private", true);

        HttpEntity<MultiValueMap<String, Object>> requestEntity = new HttpEntity<MultiValueMap<String, Object>>(paramMap,requestHeaders);
		
		// get请求方式
		try {
			ResponseEntity<String> response = restTemplate.exchange(createRepoUrl, HttpMethod.POST, requestEntity, String.class);
			String pushInfo = response.getBody();
			log.debug("projectInfo = " + pushInfo);
			
			JSONObject pushInfoJSON = JSONObject.parseObject(pushInfo) ; 
			String url = pushInfoJSON.getString("html_url") ; 
			String repoId = pushInfoJSON.getString("id") ; 
		
			info.setGitProjectId(repoId) ;
			info.setGitProjectLink(url) ;
			
		} catch (RestClientException e1) {
			e1.printStackTrace() ;
			log.error(e1.getMessage()) ;
		}
	}

	@Override
	public ProjectInfoDto initGiteaRepo(ProjectInfoDto info, Map<String, byte[]> data, BuildGitEntity e) {
		
//		info.setProjectCode("testProj" + RandomUtil.getRandom().nextInt());
		
		String accessToken = e.getAccessPrivateToken();
		GroupDto groupDto = info.getGroup() ; 
		
		String owner = null ; 
	
		if(groupDto == null) {
			JSONObject json = JSONObject.parseObject(e.getBingGitInfo())  ; 
			owner = json.getString("login")  ;
		}else {
			owner = groupDto.getName() ;
		}
		
		createGiteaRepo(info, e , owner , groupDto);

		String repo = info.getProjectCode() ; 
		String pushUrl = "http://git.linesno.com/api/v1/repos/" + owner + "/" + repo + "/contents/";
		
		log.debug("pushUrl = {}" , pushUrl);

		for (String gitPath : data.keySet()) {
			log.debug("key = " + gitPath + " , value = " + data.get(gitPath) + ", path = " + data.get(gitPath).length);

			HttpHeaders requestHeaders = new HttpHeaders();
			requestHeaders.add("accept", "application/json");
			requestHeaders.add("Authorization", "token " + accessToken);

			RestTemplate restTemplate = new RestTemplate();

			// 封装参数，千万不要替换为Map与HashMap，否则参数无法传递
			MultiValueMap<String, Object> paramMap = new LinkedMultiValueMap<String, Object>();
			paramMap.add("access_token", accessToken);
			paramMap.add("owner", owner);
			paramMap.add("repo", info.getProjectCode());
			paramMap.add("filepath", gitPath);
			paramMap.add("branch", "master") ; 
			paramMap.add("content", Base64.getEncoder().encode(data.get(gitPath).length==0?("// init file").getBytes():data.get(gitPath))) ; 
			paramMap.add("message", "代码生成器初始化项目库");
			
			HttpEntity<MultiValueMap<String, Object>> requestEntity = new HttpEntity<MultiValueMap<String, Object>>(paramMap,requestHeaders);
			
			// get请求方式
			String pushFileUrl = pushUrl + gitPath;
			log.debug("pushFileUrl = {}" , pushFileUrl) ;
		
			if(!gitPath.endsWith("README.md")) {
				ResponseEntity<String> response = restTemplate.exchange(pushFileUrl, HttpMethod.POST, requestEntity, String.class);
				String pushInfo = response.getBody();
				log.debug("pushInfo = " + pushInfo);
			}
		}

		return info;
	}

	private void createGiteaRepo(ProjectInfoDto info, BuildGitEntity e, String owner, GroupDto groupDto) {
		
		String accessToken = e.getAccessPrivateToken();

		String createRepoUrl = "http://git.linesno.com/api/v1/user/repos";
		
		HttpHeaders requestHeaders = new HttpHeaders();
		requestHeaders.add("accept", "application/json");
		requestHeaders.add("Authorization", "token " + accessToken);

		RestTemplate restTemplate = new RestTemplate();
		
		// 封装参数，千万不要替换为Map与HashMap，否则参数无法传递
        MultiValueMap<String, Object> paramMap = new LinkedMultiValueMap<String, Object>();
        paramMap.add("name", info.getProjectCode());
        paramMap.add("description", "工程描述");
        paramMap.add("auto_init", true);
        paramMap.add("private", true);
//        paramMap.add("license", "工程版权文件");
//        paramMap.add("readme", "初始化工程");
        
       if(groupDto != null) {
    	   createRepoUrl = "http://git.linesno.com/api/v1/org/"+groupDto.getName()+"/repos" ; 
       }

        HttpEntity<MultiValueMap<String, Object>> requestEntity = new HttpEntity<MultiValueMap<String, Object>>(paramMap,requestHeaders);
		
		// get请求方式
		try {
			ResponseEntity<String> response = restTemplate.exchange(createRepoUrl, HttpMethod.POST, requestEntity, String.class);
			String pushInfo = response.getBody();
			log.debug("projectInfo = " + pushInfo);
			
		} catch (RestClientException e1) {
			e1.printStackTrace() ;
			log.error(e1.getMessage()) ;
		}
	}

}
